package cn.iocoder.yudao.module.signature.controller.app.application;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.ApiCommonResult;
import cn.iocoder.yudao.module.member.api.order.AppMemberCertificateOrderReq;
import cn.iocoder.yudao.module.member.api.order.CertificateOrderApi;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.signature.controller.admin.device.vo.AppleDeviceResp;
import cn.iocoder.yudao.module.signature.controller.app.application.vo.MemberCertificateOrderDto;
import cn.iocoder.yudao.module.signature.service.device.AppleDeviceService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.ZoneId;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ERROR_MESSAGE_REPEAT;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.THIRD_TYPE_ERROR;

@Tag(name = "对外接口")
@RestController
@RequestMapping("/signature")
@Slf4j
public class DeviceController {
    @Resource
    private MemberUserApi memberUserApi;
    @Resource
    private AppleDeviceService appleDeviceService;
    @Resource
    private CertificateOrderApi certificateOrderApi;
    @Resource
    private HttpServletRequest httpServletRequest;

    /**
     * 查询证书
     * http://localhost:48080/app-api/signature/api/Getcertificate
     */
    @PostMapping("/api/Getcertificate")
    @PermitAll
    public ApiCommonResult getCertificate() {
        String token = httpServletRequest.getParameter("token");
        String certificateId = httpServletRequest.getParameter("id");
        String udid = httpServletRequest.getParameter("udid");
        if (StringUtils.isBlank(token)) {
            return ApiCommonResult.error("token不能为空");
        }

        // 1. 用户校验
        MemberUserRespDTO user = memberUserApi.getUserByUserToken(token);
        if (user == null || user.getId() == null) {
            return ApiCommonResult.error("token不正确");
        }

        if (StringUtil.isBlank(certificateId) && StringUtil.isBlank(udid)) {
            return ApiCommonResult.error("证书ID或UDID至少需要一个不为空");
        }

        // 2. 查询设备信息，优先按证书ID，否则按UDID
        AppleDeviceResp device = null;
        if (StringUtil.isNotBlank(certificateId)) {
            device = appleDeviceService.selectCertificate(certificateId, user.getId());
            if (device == null || device.getId() == null) {
                return ApiCommonResult.error("证书ID不存在");
            }
        } else {
            device = appleDeviceService.getDeviceByUdidAndUserId(udid, user.getId());
            if (device == null || device.getId() == null) {
                return ApiCommonResult.error("UDID不存在");
            }
        }

        // 3. 获取证书相关参数
        // 这些参数名字你要和你的 DO/POJO 对应
        String base64mp = device.getMobileprovision();
        String base64p12 = device.getP12();
        Integer type = device.getType();
        Integer chi = device.getPool();
        Long addTime = device.getAddTime();
        // 售后
        Boolean shouhou = device.isWarranty();
        Map<String, Object> data = new JSONObject();
        data.put("id", device.getId());
        data.put("pname", device.getPName());
        // 添加时间
        data.put("addtime", addTime);
        // 	0公共池 1独立池
        data.put("pool", chi);
        // 证书类别 0实时 1预约
        data.put("type", type);
        // base64描述文件
        data.put("mobileprovision", fileToBase64(base64mp));
        // base64 P12文件
        data.put("p12", fileToBase64(base64p12));
        // 证书状态 是否掉签

        data.put("state", device.isState());
        // 是否为售后证书
        data.put("warranty", shouhou);
        // 售后截止时间
        data.put("warranty_time", device.getWarrantyTime().atZone(ZoneId.systemDefault()).toEpochSecond());
        data.put("shtype", device.getShtype());
        log.info(JSONUtil.toJsonStr(data));
        return ApiCommonResult.success(data);
    }

    /**
     * 添加设备（秒出）
     * http://localhost:48080/app-api/signature/api/adddevice
     *
     * @return
     */
    @PostMapping("/api/adddevice")
    @PermitAll
    public ApiCommonResult addDevice() {
        // 设备的UDID
        String udid = httpServletRequest.getParameter("udid");
        // 0或空为公共池 1独立池 2自动选择 优先独立池，独立池无法添加转为公共池
        String type = httpServletRequest.getParameter("type");
        // 备注
        String beizhu = httpServletRequest.getParameter("beizhu");
        // 证书类型：0躺平版，1普通版，2加强版，3稳定版
        String warranty = httpServletRequest.getParameter("warranty");
        if (StringUtils.isBlank(udid)) {
            return ApiCommonResult.error("设备的UDID不能为空");
        }
        if (StringUtils.isBlank(warranty)) {
            return ApiCommonResult.error("证书类型不能为空");
        }
        if (StringUtils.isBlank(type)) {
            type = "0";
        }

        String token = httpServletRequest.getParameter("token");
        if (StringUtils.isBlank(token)) {
            return ApiCommonResult.error("token不能为空");
        }
        MemberUserRespDTO user = memberUserApi.getUserByUserToken(token);
        if (user == null || user.getId() == null) {
            return ApiCommonResult.error("token不正确");
        }
        AppMemberCertificateOrderReq appOrderVo = new AppMemberCertificateOrderReq();
        appOrderVo.setUserId(user.getId());
        appOrderVo.setUdid(udid);
        // 购买类型0:公共池 1:独立池
        appOrderVo.setPoolType(type);
        appOrderVo.setRemark(beizhu);
        appOrderVo.setDeviceType("iphone");
        // 购买类型 秒出 0  ；预约 1
        appOrderVo.setClassType("0");
        //购买类型转换
        //  0躺平版 vt2 ，1普通版 VT3，2加强版VT5，3稳定版VT6 ,4摆烂版VT1 ,5  VT4

        appOrderVo.setWarrantyType(warranty);
        if("0".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT2");
        }else if ("1".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT3");
        }else if ("2".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT5");
        }else if ("3".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT6");
        }else if ("4".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT1");
        }else if ("5".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT4");
        }else {
            throw exception(THIRD_TYPE_ERROR);
        }
        ApiCommonResult apiCommonResult = certificateOrderApi.createOrder(appOrderVo);
        if (!Objects.equals(apiCommonResult.getCode(), ApiCommonResult.SUCCESS)) {
            return ApiCommonResult.error(apiCommonResult.getMsg());
        }
        MemberCertificateOrderDto orderDto = (MemberCertificateOrderDto) apiCommonResult.getData();
        JSONObject resp = new JSONObject();
        // 证书ID
        resp.set("id", orderDto.getId());
        // 0公共池 1独立池
        resp.set("pool", orderDto.getPoolType());
        //证书类别  0实时 1预约
        resp.set("type", orderDto.getClassType());
        //添加时间
        resp.set("addTime", orderDto.getCreateTime().atZone(ZoneId.systemDefault()).toEpochSecond());
        //base64描述文件
        resp.set("mobileprovision", fileToBase64(orderDto.getMpUrl()));
        //base64 P12文件
        resp.set("p12", fileToBase64(orderDto.getP12Url()));
        //证书状态 是否掉签
        resp.set("state", !orderDto.getDropFlag());
        //是否为售后证书
        resp.set("warranty", true);
        // //售后截止时间
        resp.set("warranty_time", orderDto.getTimeout());
        resp.set("pname", orderDto.getCerName());
        resp.set("shtype", warranty);
        return ApiCommonResult.success(resp);
    }


    /**
     * 添加设备（预约）
     * http://localhost:48080/app-api/signature/api/addyydevice
     *
     * @return
     */
    @PostMapping("/api/addyydevice")
    @PermitAll
    public ApiCommonResult addyyDevice() {
        // 设备的UDID
        String udid = httpServletRequest.getParameter("udid");
        // 0或空为公共池 1独立池 2自动选择 优先独立池，独立池无法添加转为公共池
        String type = httpServletRequest.getParameter("type");
        // 备注
        String beizhu = httpServletRequest.getParameter("beizhu");
        // 证书类型：0躺平版，1普通版，2加强版，3稳定版
        String warranty = httpServletRequest.getParameter("warranty");
        if (StringUtils.isBlank(udid)) {
            return ApiCommonResult.error("设备的UDID不能为空");
        }
        if (StringUtils.isBlank(warranty)) {
            return ApiCommonResult.error("证书类型不能为空");
        }
        if (StringUtils.isBlank(type)) {
            type = "0";
        }
        String token = httpServletRequest.getParameter("token");
        if (StringUtils.isBlank(token)) {
            return ApiCommonResult.error("token不能为空");
        }
        MemberUserRespDTO user = memberUserApi.getUserByUserToken(token);
        if (user == null || user.getId() == null) {
            return ApiCommonResult.error("token不正确");
        }
        AppMemberCertificateOrderReq appOrderVo = new AppMemberCertificateOrderReq();
        appOrderVo.setUserId(user.getId());
        appOrderVo.setUdid(udid);
        // 购买类型0:公共池 1:独立池
        appOrderVo.setPoolType(type);
        appOrderVo.setRemark(beizhu);
        appOrderVo.setDeviceType("iphone");
        // 购买类型 秒出 0  ；预约 1
        appOrderVo.setClassType("1");
        appOrderVo.setWarrantyType(warranty);
        if("0".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT2");
        }else if ("1".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT3");
        }else if ("2".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT5");
        }else if ("3".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT6");
        }else if ("4".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT1");
        }else if ("5".equals(warranty)){
            appOrderVo.setVersionTypeCode("VT4");
        }else {
            throw exception(THIRD_TYPE_ERROR);
        }
        ApiCommonResult apiCommonResult = certificateOrderApi.createOrder(appOrderVo);
        if (!Objects.equals(apiCommonResult.getCode(), ApiCommonResult.SUCCESS)) {
            return ApiCommonResult.error(apiCommonResult.getMsg());
        }
        MemberCertificateOrderDto orderDto = (MemberCertificateOrderDto) apiCommonResult.getData();
        JSONObject resp = new JSONObject();
        // 证书ID、
        if (!ObjectUtil.isEmpty(orderDto.getCerName())){
            resp.set("pname", orderDto.getCerName());
        }
        resp.set("id", orderDto.getId());
        //base64描述文件
        resp.set("mobileprovision", fileToBase64(orderDto.getMpUrl()));
        //base64 P12文件
        resp.set("p12", fileToBase64(orderDto.getP12Url()));

        // 0公共池 1独立池
        resp.set("pool", orderDto.getPoolType());
        //证书类别  0实时 1预约
        resp.set("type", orderDto.getClassType());
        //添加时间
        resp.set("addTime", orderDto.getCreateTime().atZone(ZoneId.systemDefault()).toEpochSecond());
        //证书状态 是否掉签  本系统与其他系统有差异 所以取反
        resp.set("state", !orderDto.getDropFlag());
        //是否为售后证书
        resp.set("warranty", true);
        // //售后截止时间
        resp.set("warranty_time", orderDto.getTimeout());
        resp.set("shtype", warranty);
        return ApiCommonResult.success(resp);
    }

    private static String fileToBase64(String fileUrl) {
        if (StringUtils.isBlank(fileUrl)) {
            return "";
        }
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);

            try (InputStream in = conn.getInputStream();
                 ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                byte[] buffer = new byte[4096];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
                return Base64.getEncoder().encodeToString(baos.toByteArray());
            } finally {
                conn.disconnect();
            }
        } catch (Exception e) {
            return "";
        }
    }


}
